package top.lemna.code.generate;

import java.io.IOException;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import freemarker.template.TemplateException;
import top.lemna.code.generate.util.JavaParserUtils;

public class MyGenerator {
  private final String className;

  private final String domainName;

  private final String templatePath;

  // 输出的包名，与 @see outPath 对应
  private final String basePackage;

  // 输出的路径
  private final String outPath;

  private final String artifactName;

  public MyGenerator(String className, String basePackage, String outPath, String templatePath) {
    super();
    this.className = className;
    this.templatePath = templatePath;
    this.outPath = outPath;
    this.basePackage = basePackage;
    this.artifactName = getArtifactName(basePackage);
    this.domainName = getDomainName(className);
  }

  public void generator() throws Exception {
    ClassElement classElement = JavaParserUtils.parserJava(className);
    List<JavaField> list = classElement.getFieldList();
    String classComment = classElement.getClassComment().replaceAll("<br>", "");
    // 生成 Repository
    generatorRepository(list);
    // 生成 Service
    generatorService(list);
    // 生成 DTO
    generatorQueryBo(list);
    generatorAddBo(list);
    generatorEditBo(list);
    // 生成 Command
    generatorAddCommand(list, classComment);
    generatorEditCommand(list, classComment);
    generatorQueryCommand(list, classComment);
    generatorMapper(list, classComment);
    // 生成 Specification
    generatorSpecification(list);
    // 生成 Controller
    generatorController(list, classComment);
    // 生成 VO
    generatorVo(list, classComment);
    // 生成 NotExistException
    generatorNotExistException(list, classComment);
    // 生成 AlreadyExistException
    generatorAlreadyExistException(list, classComment);

  }

  private void generatorRepository(List<JavaField> list) throws IOException, TemplateException {
    String templateName = "persistence/Repository.ftl";
    String outFilePath = outPath   + "/service/repository/";
    String outFileName = domainName + "Repository.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("domain", domainName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }

  private void generatorService(List<JavaField> list) throws IOException, TemplateException {
    String templateName = "persistence/Service.ftl";
    String outFilePath = outPath   + "/service/service/";
    String outFileName = domainName + "Service.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("domain", domainName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }

  private void generatorQueryBo(List<JavaField> list) throws IOException, TemplateException {
    String templateName = "persistence/Query.ftl";
    String outFilePath = outPath   + "/service/query/";
    String outFileName = domainName + "Query.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("domain", domainName);
    dataMap.put("artifact", artifactName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }

  private void generatorAddBo(List<JavaField> list) throws IOException, TemplateException {
    String templateName = "persistence/AddBo.ftl";
    String outFilePath = outPath   + "/service/bo/";
    String outFileName = domainName + "AddBo.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("domain", domainName);
    dataMap.put("artifact", artifactName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }

  private void generatorEditBo(List<JavaField> list) throws IOException, TemplateException {
    String templateName = "persistence/EditBo.ftl";
    String outFilePath = outPath   + "/service/bo/";
    String outFileName = domainName + "EditBo.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("domain", domainName);
    dataMap.put("artifact", artifactName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }

  private void generatorAddCommand(List<JavaField> list, String classComment)
      throws IOException, TemplateException {
    String templateName = "web/AddCommand.ftl";
    String outFilePath = outPath + "/command/";
    String outFileName = domainName + "AddCommand.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("classComment", classComment);
    dataMap.put("domain", domainName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }

  private void generatorEditCommand(List<JavaField> list, String classComment)
      throws IOException, TemplateException {
    String templateName = "web/EditCommand.ftl";
    String outFilePath = outPath + "/command/";
    String outFileName = domainName + "EditCommand.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("classComment", classComment);
    dataMap.put("domain", domainName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }


  private void generatorQueryCommand(List<JavaField> list, String classComment)
      throws IOException, TemplateException {
    String templateName = "web/QueryCommand.ftl";
    String outFilePath = outPath + "/command/";
    String outFileName = domainName + "QueryCommand.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("classComment", classComment);
    dataMap.put("domain", domainName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }


  private void generatorMapper(List<JavaField> list, String classComment)
      throws IOException, TemplateException {
    String templateName = "web/Mapper.ftl";
    String outFilePath = outPath + "/command/";
    String outFileName = domainName + "Mapper.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("classComment", classComment);
    dataMap.put("domain", domainName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }


  private void generatorSpecification(List<JavaField> list) throws IOException, TemplateException {
    String templateName = "web/Specification.ftl";
    String outFilePath = outPath   + "/service/specification/";
    String outFileName = domainName + "Specification.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("domain", domainName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }

  private void generatorController(List<JavaField> list, String classComment)
      throws IOException, TemplateException {
    String templateName = "web/Controller.ftl";
    String outFilePath = outPath + "/controller/";
    String outFileName = domainName + "Controller.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("classComment", classComment);
    dataMap.put("domain", domainName);
    dataMap.put("artifact", artifactName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }


  private void generatorVo(List<JavaField> list, String classComment)
      throws IOException, TemplateException {
    String templateName = "web/Vo.ftl";
    String outFilePath = outPath + "/controller/vo/";
    String outFileName = domainName + "Vo.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("classComment", classComment);
    dataMap.put("domain", domainName);
    dataMap.put("artifact", artifactName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }
  

  private void generatorNotExistException(List<JavaField> list, String classComment)
      throws IOException, TemplateException {
    String templateName = "exceptions/NotExistException.ftl";
    String outFilePath = outPath + "/service/exceptions/";
    String outFileName = domainName + "NotExistException.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("classComment", classComment);
    dataMap.put("domain", domainName);
    dataMap.put("artifact", artifactName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }
  
  private void generatorAlreadyExistException(List<JavaField> list, String classComment)
      throws IOException, TemplateException {
    String templateName = "exceptions/AlreadyExistException.ftl";
    String outFilePath = outPath + "/service/exceptions/";
    String outFileName = domainName + "AlreadyExistException.java";
    Map<String, Object> dataMap = new HashMap<String, Object>();
    dataMap.put("classPath", basePackage);
    dataMap.put("classComment", classComment);
    dataMap.put("domain", domainName);
    dataMap.put("artifact", artifactName);
    dataMap.put("fieldList", list);
    FreemarkerGenerator fg = new FreemarkerGenerator(templatePath);
    fg.generator(dataMap, templateName, outFilePath, outFileName);
  }


  static String getDomainName(String className) {
    return className.replaceAll("\\\\", "/")
        .substring(className.lastIndexOf("/"), className.lastIndexOf(".")).replaceAll("/", "");
  }

  static String getArtifactName(String basePackage) {
    return basePackage.substring(basePackage.lastIndexOf(".") + 1);
  }
}
